#include "EXER.h"
#include <iostream>

EXER::EXER()
{
    this->_stream = nullptr;
    this->page = 0;
    this->pos = 0;
    this->file_size = 0;
    this->halt = false;
}

EXER::EXER(FILE* fp)
{
    this->_stream = fp;
    this->page = 0;
    this->pos = 0;
    this->file_size = 0;
    this->halt = false;
    if (this->_stream == nullptr)return;
    fseek(this->_stream, 0, SEEK_END);
    this->file_size = ftell(this->_stream);
    fseek(this->_stream, 0, SEEK_SET);
    this->jump_to_page(0);
    WORD a = 0;
    BYTE tmp; 
    tmp = this->buf[this->pos];
    this->next_byte();
    a = tmp;
    tmp = this->buf[this->pos];
    this->next_byte();
    a = (a << 4) | tmp;
    this->vmem = VMEM(a);
}

bool EXER::jump_to_page(size_t p)
{
    if (this->halt)return false;
    if (this->file_size <= (size_t(p) << 8))
        return false;
    this->page = p;
    this->pos = 0;
    this->buf = std::vector<BYTE>(1 << 8);
    for (size_t i = 0; i < 256; i++)
    {
        if (((size_t(this->page) << 8) | this->pos) >= this->file_size)
            break;
        this->buf[i] = fgetc(this->_stream);
    }
    return true;
}

BYTE EXER::next_byte()
{
    if (this->halt)
        return 0x00;
    if (((size_t(this->page) << 8) | this->pos) >= this->file_size)
    {
        std::cout << "out" << int(this->page) << " " << (int)this->pos << " " << this->file_size << std::endl;
        return 0x00;
    }
    if (this->pos != 1 << 8)
    {
        this->pos++;
        return this->buf[this->pos];
    }
    else
    {
        this->pos = 0;
        this->jump_to_page(this->page + 1);
        return this->buf[0];
    }
}

void EXER::execute_command()
{
    if (this->halt)return;
    BYTE cmd = this->buf[this->pos];
    this->next_byte();
    BYTE tmp, type;
    WORD a, b, c;
    //TODO 
}

bool EXER::is_halt() const
{
    return this->halt;
}
